home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-serious-
/
programming
/
basic
/
mildred
/
lha
/
ilbmviewer.lha
/
Chunky.ascii
next >
Wrap
Text File
|
1999-03-03
|
12KB
|
356 lines
; Chunky routines
;ILBM-loader constants
#ILBM_FileHandle=0
#FORMid=$464F524D ; "FORM"
#ILBMid=$494C424D ; "ILBM"
#BMHDid=$424D4844 ; "BMHD"
#CMAPid=$434D4150 ; "CMAP"
#CAMGid=$43414D47 ; "CAMG"
#BODYid=$424F4459 ; "BODY"
NEWTYPE.BMHD
Width.w
Height.w
X.w
Y.w
Planes.b
Masking.b
Compression.b
Pad1.b
Transparent.w
XAspect.b
YAaspect.b
SourceWidth.w
SourceHeight.w
End NEWTYPE
NEWTYPE._RGBComponents
_Red.l
_Green.l
_Blue.l
End NEWTYPE
NEWTYPE._PaletteData
NumCols.w
Zero.w
_RGBs._RGBComponents[256]
Zero2.l
End NEWTYPE
Statement ChunkyClearscreen4{ChunkyBuf.l,BufHeight.w,OpWidth.w,DestWidth.w,Value.l}
;Clears the rightmost 4-pixel-width column in the chunky buffer to Value.l
;Covers up the longword clip/wrap buffer. Column is rightmost to OpWidth, DestWidth supplies modulo
MOVE.l d0,a0 ; Chunky output
AND.l #$FFFF,d1 ; Only word
SUBQ.l #1,d1 ; Loopcounter
AND.l #$FFFF,d3 ; Modulo
SUBQ.l #4,d3 ; Modulo-4 to accomodate move.l
AND.l #$FFFF,d2 ; Only word
SUBQ.l #4,d2 ; OpWidth-4, x start position
ADD.l d2,a0 ; Source position
ChunkyClear4
MOVE.l d4,(a0)+ ; Clear 4 pixels
ADD.l d3,a0 ; Dest Modulo
DBRA d1,ChunkyClear4
AsmExit
End Statement
Statement ChunkyClearscreen32{ChunkyBuf.l,BufHeight.w,Value.l,Width.w}
;Clears chunky screen, Width*BufHeight pixels (Width multiples of 32!)
MOVE.l a3,-(a7)
MOVE.l d0,a0 ; Chunky output
MOVE.l d2,d0 ; Get value
AND.l #$FFFF,d3 ; Only word
MOVE.l d3,d2 ; Width
AND.l #$FFFF,d1 ; Only word
MULU d1,d2 ; Size in bytes
ADD.l d2,a0 ; To end of buffer
SUBQ.l #1,d1 ; Init YLoop
EXG.l d0,d3 ; 1
MOVE.l d3,d4 ; 2
MOVE.l d3,d5 ; 3
MOVE.l d3,d6 ; 4
MOVE.l d3,d7 ; 5
MOVE.l d3,a1 ; 6
MOVE.l d3,a2 ; 7
MOVE.l d3,a3 ; 8 longwords = 32 pixels
LSR.w #2+3,d0 ; Width in longwords (2=2^2=4=longwords, 3=2^3=8=groups of 8 longwords)
SUBQ.l #1,d0 ; Xloopcounter
ChunkyClrLoopY
MOVE.l d0,d2 ; Init XLoop
ChunkyClrLoopX
MOVEM.l d3-d7/a1-a3,-(a0) ; Clear 32 pixels
DBRA d2,ChunkyClrLoopX
DBRA d1,ChunkyClrLoopY
MOVE.l (a7)+,a3
AsmExit
End Statement
Statement ChunkyCopy16{ChunkyBufA.l,ChunkyBufB.l,BufHeight.w,CPU.b,OpWidth.w,DestWidth.w}
;Copies one chunky screen to another, Width*BufHeight pixels (Width multiples of 16!)
;Seperate routines for 040+ (move16) and 030- (movem)
;Width of source buffer and dest buffer will be the same and use the same modulo but OpWidth can be narrower
MOVE.l d0,a0 ; Chunky source
MOVE.l d1,a1 ; Chunky destination
MOVE.w d2,d0 ; Height
AND.l #$FFFF,d0 ; Only word
SUBQ.l #1,d0 ; d0=YLoop
AND.l #$FFFF,d4 ; Only word
AND.l #$FFFF,d5 ; Only word
SUB.l d4,d5 ; Dest modulo
LSR.w #2+2,d4 ; Longwords (2=2^2=4=longwords, 2=2^2=4=groups of 4 longwords
SUBQ.l #1,d4 ; loop
MOVE.l d4,d1 ; d1=XLoop
MOVE.l d5,d2 ; d2=Dest Modulo
CMP.b #4,d3 ; 040+?
BEQ ChunkyCopy040 ; Yes, do move16's
ADD.l #16,a1
ChunkyCopy030
ChunkyCopy030y
MOVE.l d1,d3 ; d3=Xloop
ChunkyCopy030x
MOVEM.l (a0)+,d4-d7
MOVEM.l d4-d7,-(a1) ; 16 pixels
ADD.l #32,a1
DBRA d3,ChunkyCopy030x
ADD.l d2,a0 ; Source modulo
ADD.l d2,a1 ; Dest modulo
DBRA d0,ChunkyCopy030y
AsmExit
ChunkyCopy040
ChunkyCopy040y
MOVE.l d1,d3 ; d3=Xloop
ChunkyCopy040x
Dc.l $F6209000 ; move16 (a0)+,(a1)+ ; 16 bytes
DBRA d3,ChunkyCopy040x
ADD.l d2,a0 ; Source modulo
ADD.l d2,a1 ; Dest modulo
DBRA d0,ChunkyCopy040y
AsmExit
End Statement
Statement ILBMP2C{Src.l,Dest.l,ChunkyBytes.l,PlanarBytes.l}
;Convert an interleaved planar buffer to chunky (eight-pass)
;Bytes must be even (nearest 16 pixels)
MOVE.l d1,a1 ; Dest
MOVE.l d2,a2 ; End address
MOVE.l d3,d2 ; Plane byte width (for plane selection)
MOVEQ.l #7,d3 ; Planes-1
ADD.l a1,a2 ; Point to end
P2Cplaneloop
MOVE.l d1,a1 ; Start of dest
MOVEQ.l #7,d6 ; Temp
SUB.l d3,d6 ; Reverse plane number (start at 0)
MOVE.l d0,a0 ; Source
MOVE.l d2,d7 ; Get size
MULU d6,d7 ; Offset
ADD.l d7,a0 ; Point
P2Cwordloop
MOVE.w (a0)+,d4 ; Get planar word
MOVE.w #15,d5 ; bit loopcounter
P2Cbitloop
LSL.w #1,d4 ; Put leftmost bit into eXtend flag
MOVE.b (a1),d6 ; Get existing destination byte
ROXR.b #1,d6 ; Rotate it right, bringing in the eXtend flag on the left
MOVE.b d6,(a1)+ ; Update the destination pixel
DBRA d5,P2Cbitloop ; next planar bit (and next chunky pixel)
CMP.l a1,a2 ; At the end of a line of chunky pixels yet?
BGT P2Cwordloop ; Yes, so do the next 16 pixels of planar (word)
DBRA d3,P2Cplaneloop ; Next plane
AsmExit
End Statement
Statement ILBMReadPal{PalNum.w,Cols.w}
;Grab a palette from the ILBM file into a palette object
InitPalette PalNum,Cols
*PalTmp.palette=Addr Palette(PalNum)
*PalDat._PaletteData=*PalTmp\_pdata
R.l=0
G.l=0
B.l=0
For CLoop.w=0 To Cols-1
ReadMem #ILBM_FileHandle,&R+3,1
ReadMem #ILBM_FileHandle,&G+3,1
ReadMem #ILBM_FileHandle,&B+3,1
*RGBTmp._RGBComponents=*PalDat\_RGBs[CLoop]
*RGBTmp\_Red=(((((R LSL 8)|R) LSL 8)| R)LSL 8)|R
*RGBTmp\_Green=(((((G LSL 8)|G) LSL 8)| G)LSL 8)|G
*RGBTmp\_Blue=(((((B LSL 8)|B) LSL 8)| B)LSL 8)|B
Next CLoop
End Statement
Function.b LoadLandILBM{FName$,PalNum.w,CWidth.w,CHeight.w,CDest.l,CDest2.l}
;ILBM-picture land-loader
SHARED LandWidth ; Now needed
SHARED ILBMHAM.l,IsAGA.b
If Exists(FName$)
suc=OpenFile(#ILBM_FileHandle,FName$)
If suc=False Then Function Return False
Else
Function Return False
EndIf
FormCheck.l=0
ReadMem #ILBM_FileHandle,&FormCheck,4
If FormCheck<>#FORMid Then Function Return False
FormSize.l=0
TempLong.l=0
ChunkSize.l=0
ReadMem #ILBM_FileHandle,&FormSize,4
ReadMem #ILBM_FileHandle,&TempLong,4
FilePos.l=12
If PalNum=-1 Then Complete.w=2 Else Complete.w=0
If TempLong=#ILBMid
While ((FilePos<FormSize)&(NOT(Eof(#ILBM_FileHandle))))&(Complete<3)
ReadMem #ILBM_FileHandle,&TempLong,4
ReadMem #ILBM_FileHandle,&ChunkSize,4
FilePos+8
ChunkSize+(ChunkSize&1)
Select TempLong
Case #CMAPid
;Colourmap chunk
If PalNum>-1 Then ILBMReadPal{PalNum,ChunkSize/3}
Case #BMHDid
;BitmapHeader chunk
If ChunkSize>=SizeOf.BMHD
TmpBmHd.BMHD\Width=0
ReadMem #ILBM_FileHandle,&TmpBmHd,SizeOf.BMHD
If TmpBmHd\Planes>8
Complete=4 ; Not allowed 24-bit iff's
Else
EBWidth.w=TmpBmHd\Width
If EBWidth>(EBWidth AND $FFFFFFF0) Then EBWidth=(EBWidth+16) AND $FFFFFFF0 ; Handle uneven byte widths
EBWidth.w=EBWidth LSR 3
If AvailMem_(#MEMF_FAST)<EBWidth*8 Then Function Return False
BufAdr.l=AllocMem(EBWidth*8,$10000) ; One interleaved line (up to 8 planes)
If BufAdr=0 Then Complete=4
EndIf
EndIf
Case #CAMGid
;Amigamodes chunk
CAMGmodes.l=0
ReadMem #ILBM_FileHandle,&CAMGmodes,4
If ((CAMGmodes AND $00000800)>0) Then ILBMHAM.l=$800
Case #BODYid
;Body chunk
If BufAdr<>0
If TmpBmHd\Compression=0
For YLoop.w=0 To TmpBmHd\Height-1
For PLoop.w=0 To TmpBmHd\Planes-1
PlanePtr.l=BufAdr+(PLoop*EBWidth)
ReadMem #ILBM_FileHandle,PlanePtr,EBWidth
Next PLoop
If YLoop<CHeight-1
out.l=LandWidth*YLoop
ILBMP2C{BufAdr,CDest+out,CWidth,EBWidth} ; Main chunky output
If CDest2<>0 Then ILBMP2C{BufAdr,CDest2+out,CWidth,EBWidth} ; Duplicate
For PPos.l=BufAdr To BufAdr+(EBWidth*8)-1 Step 2
NPokeW PPos,0
Next PPos
EndIf
Next YLoop
Else
PStep.l=0
GfxCur.b=0
GfxLen.w=0
GfxByte.b=0
PLoop.w=0
YLoop.w=0
PlanePtr.l=BufAdr
While YLoop<TmpBmHd\Height
ReadMem #ILBM_FileHandle,&GfxCur,1
If GfxCur>=0
GfxLen=GfxCur+1
ReadMem #ILBM_FileHandle,PlanePtr,GfxLen
PlanePtr+GfxLen
PStep+GfxLen
Else
If GfxCur>-128
GfxLen=-GfxCur+1
ReadMem #ILBM_FileHandle,&GfxByte,1
PStep+GfxLen
For BLoop.w=0 To GfxLen-1
NPokeB PlanePtr,GfxByte
PlanePtr+1
Next BLoop
EndIf
EndIf
If PStep>=EBWidth
PLoop+1
If PLoop=TmpBmHd\Planes
If YLoop<CHeight-1
out.l=LandWidth*YLoop
ILBMP2C{BufAdr,CDest+out,CWidth,EBWidth} ; Main chunky output
If CDest2<>0 Then ILBMP2C{BufAdr,CDest2+out,CWidth,EBWidth} ; Duplicate
For PPos.l=BufAdr To BufAdr+(EBWidth*8)-1 Step 2
NPokeW PPos,0
Next PPos
EndIf
YLoop+1
PLoop=0
EndIf
PlanePtr=BufAdr+(EBWidth*PLoop)
PStep=0
EndIf
Wend
EndIf
Complete=3
Else
Complete=4
EndIf
End Select
FilePos+ChunkSize
FileSeek #ILBM_FileHandle,FilePos
Wend
EndIf
CloseFile #ILBM_FileHandle
If BufAdr<>0 Then FreeMem BufAdr,EBWidth*8
If Complete=3
Function Return True
Else
Function Return False
EndIf
End Function
Function.b InitLand{FName$,PalNum.w,WidthClip.l,HeightClip.l}
;Initialise land
SHARED LandBase.l,LandBase2.l,LandWidth.l,LandHeight.l,HeightMultiplier.l,HeightAdder.l
SHARED LandBuffer.l,LandBuffer2.l,PrefDisplayWidth,GlobalTemp,PrefDisplayHeight,ILBMActualHeight.l
If Exists(FName$)
suc=OpenFile(#ILBM_FileHandle,FName$)
If suc=False Then Function Return False
Else
Function Return False
EndIf
FormCheck.l=0
ReadMem #ILBM_FileHandle,&FormCheck,4
If FormCheck<>#FORMid Then Function Return False
TempLong.l=0
ReadMem #ILBM_FileHandle,&TempLong,4
ReadMem #ILBM_FileHandle,&TempLong,4
CloseFile #ILBM_FileHandle
If TempLong<>#ILBMid Then Function Return False
ILBMInfo FName$
If WidthClip=0 Then WidthClip=ILBMWidth
If HeightClip=0 Then HeightClip=ILBMHeight
Width.l=Min(WidthClip,ILBMWidth)
If Width>(Width AND $FFFFFFF0) Then Width=(Width+16) AND $FFFFFFF0 ; Handle non-aligned widths (nearest 4 pixels)
Height.l=Min(HeightClip,ILBMHeight)
If Height<PrefDisplayHeight Then YOff=PrefDisplayHeight-Height Else YOff=0
LandWidth.l=Max(Width,PrefDisplayWidth) ; Total viewable game environment width
LandHeight.l=Max(PrefDisplayHeight,(Height*HeightMultiplier)+HeightAdder) ; Total viewable game environment height
ILBMActualHeight.l=Height ; Height of actual IFF image, for copy purposes
Height=Max(Height,PrefDisplayHeight)
If AvailMem_(#MEMF_FAST)<(LandWidth*LandHeight)+16 Then Function Return False
LandBase.l=MBitmap(0,LandWidth,LandHeight)
LandBuffer.l=LandBase
If AvailMem_(#MEMF_FAST)<(LandWidth*LandHeight)+16 Then Function Return False
LandBase2.l=MBitmap(1,LandWidth,LandHeight)
LandBuffer2.l=LandBase2
LandOff.l=((LandHeight-Height)*LandWidth)+(YOff*LandWidth)
success=LoadLandILBM{FName$,PalNum,Width,Height,LandBuffer+LandOff,0}
Function Return success
End Function